package collection.map;

import collection.Printer;
import org.junit.Test;

import java.util.HashMap;
import java.util.Map;

/**
 * 1.继承自AbstractMap，基于hash算法
 * 2.支持null键和null值
 * 3.线程不安全
 * 4.无序
 */
public class HashMapTest {
    @Test
    public void testAdd() {
        Map<String, String> map = new HashMap<String, String>();

        map.put("1", "111");
        map.put("2", "");
        map.put("", "3");
        map.put(null, "444");
        map.put(null, "555");
        map.put("6", null);
        map.put("7", null);
        Printer.printMap(map);

        map.get("1");


    }


    @Test
    public void test2() {
        String str = "morningcatmeng";
        int length = 16;

        System.out.println(str.hashCode());
        System.out.println(str.hashCode() >>> 16);
        System.out.println(str.hashCode() ^ (str.hashCode() >>> 16));

        System.out.println(hash(str));
        System.out.println(hash2(str));

        System.out.println(hash(str) % length);
        System.out.println(hash2(str) & (length - 1));
    }

    static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

    static final int hash2(Object key) {
        if (key == null) {
            return 0;
        } else {
            int l = key.hashCode();
            return l ^ (l >>> 16);
        }
    }

    /**
     * HashTable的大小会尽量使用素数、奇数。而HashMap则总是使用2的幂作为哈希表的大小。
     * 我们知道当哈希表的大小为素数时，简单的取模哈希的结果会更加均匀（具体证明，见这篇文章），所以单从这一点上看，HashTable的哈希表大小选择，似乎更高明些。
     * 但另一方面我们又知道，在取模计算时，如果模数是2的幂，那么我们可以直接使用位运算来得到结果，效率要大大高于做除法。所以从hash计算的效率上，又是HashMap更胜一筹。
     * 所以，事实就是HashMap为了加快hash的速度，将哈希表的大小固定为了2的幂。当然这引入了哈希分布不均匀的问题，所以HashMap为解决这问题，又对hash算法做了一些改动。
     * 以上取自：http://www.importnew.com/24822.html
     */

    /**
     * 为什么HashMap支持null键和null值？
     * 这仅仅是因为HashMap在实现时对null做了特殊处理，将null的hashCode值定为了0，从而将其存放在哈希表的第0个bucket中。
     */
}
